package Thread;

/**
 * Created with IntelliJ IDEA.
 * Description: 阻塞队列的模拟实现
 */
class MyBlockingQueue {
    //保存数据
    private static Integer[] date = new Integer[20];
    //记录数据的个数
    private static int size = 0;
    //队列的队头位置
    private static int head = 0;
    //队列的队尾位置
    private static int tail = 0;
    private static Object locker = new Object();

    //入队列
    //由于整个方法一直在进行修改操作，因此给方法内的所有代码加上锁
    public void put(int value) throws InterruptedException {
        synchronized (locker) {
            if(size == date.length) {
                //队列满之后，应该等待，等待take唤醒
                locker.wait();
            }
            date[tail++] = value;
            size++;
            //判断 + 赋值操作 比 求余操作 对计算机来说更简单
            if(tail == date.length) {
                tail = 0;
            }
            //成功入队列一个元素之后，队列不为空，唤醒take
            locker.notify();
        }
    }

    //出队列
    //由于整个方法一直在进行修改操作，因此给方法内的所有代码加上锁
    public Integer take() throws InterruptedException {
        synchronized (locker) {
            if(size == 0) {
                //队列空了，应该阻塞，等待put唤醒
                locker.wait();
            }
            size--;
            int ret = date[head++];
            if(head == date.length) {
                head = 0;
            }
            //成功出队列一个元素，队列不为满，唤醒put
            locker.notify();
            return ret;
        }
    }

}

public class ThreadDemo26 {
    public static MyBlockingQueue queue = new MyBlockingQueue();
    public static void main(String[] args) throws InterruptedException {
        //实现一个简单的生产者消费者模型
        Thread t1 = new Thread() {
            @Override
            public void run() {
                int i = 0;
                while(true) {
                    try {
                        System.out.print("生产了：" + i + " ");
                        queue.put(i++);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                while(true) {
                    try {
                        Thread.sleep(1000);
                        Integer ret = queue.take();
                        System.out.println("消费了：" + ret);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t1.start();
        t2.start();
    }
}
